﻿using System;
using System.Diagnostics;
using System.Threading;
using System.Web;
using System.Xml;
using System.Text.RegularExpressions;
using System.IO;


namespace UrlRewrite
{
    //继承自IHttpModule接口
    public class HttpModule : System.Web.IHttpModule
    {
        private void removeHeaders(object sender, EventArgs e)
        {
            HttpContext.Current.Response.Headers.Remove("Server");
        }
        /// <summary>
        /// 实现接口的Init方法
        /// </summary>
        /// <param name="context"></param>
        public void Init(HttpApplication context)
        {
            //建立个委托让他执行下面的ReUrl_BeginRequest事件
            context.BeginRequest += new EventHandler(ReUrl_BeginRequest);
            //删除无用header
            context.PreSendRequestHeaders += new EventHandler(removeHeaders);
        }
        /// <summary>
        /// 实现接口的Dispose方法
        /// </summary>
        public void Dispose()
        {
        }
        private void ReUrl_BeginRequest(object sender, EventArgs e)
        {
            HttpContext context = ((HttpApplication)sender).Context;
            string requestPath = context.Request.Path;
            string querystring = context.Request.QueryString.ToString();
            //SiteUrls是下面的一个类，这里大家可以重构下
            foreach (SiteUrls.URLRewrite url in SiteUrls.GetSiteUrls().Urls)
            {
                //是否找到了匹配选项
                if (Regex.IsMatch(requestPath, url.Pattern, RegexOptions.None | RegexOptions.IgnoreCase))
                {
                    //最深层目录的开始位置
                    int lastF = requestPath.LastIndexOf("/");
                    lastF = lastF > 0 ? lastF : 0;
                    string newPage;
                    string newQueryString;
                    switch (url.Name)
                    {
                        case "only_pager":
                            newPage = Regex.Replace(requestPath, url.Pattern, url.Page, RegexOptions.None | RegexOptions.IgnoreCase);
                            newPage = newPage == string.Empty ? "/" : newPage;

                            //query string
                            newQueryString = Regex.Replace(requestPath, url.Pattern, url.QueryString, RegexOptions.None | RegexOptions.IgnoreCase);
                            newQueryString += "&amp;" + querystring;
                            break;
                        case "default":
                        default:
                            //path
                            newPage = Regex.Replace(requestPath, url.Pattern, url.Page, RegexOptions.None | RegexOptions.IgnoreCase);
                            newPage = newPage == string.Empty ? "/" : newPage;

                            //query string
                            newQueryString = Regex.Replace(requestPath, url.Pattern, url.QueryString, RegexOptions.None | RegexOptions.IgnoreCase);
                            if (newQueryString != string.Empty)
                            {
                                string[] param = Regex.Split(newQueryString, "-", RegexOptions.None | RegexOptions.IgnoreCase);

                                if (param.Length > 0)
                                {
                                    newQueryString = "";
                                    for (var i = 0; i < param.Length; i += 2)
                                    {
                                        if (string.IsNullOrEmpty(param[i]))
                                        {
                                            continue;
                                        }
                                        newQueryString += "&amp;" + param[i] + "=";
                                        if (i + 1 > param.Length - 1)
                                        {
                                            continue;
                                        }
                                        newQueryString += param[i + 1];
                                    }
                                }
                                else
                                {
                                    newQueryString = string.Empty;
                                }
                            }
                            newQueryString += "&amp;" + querystring;
                            break;
                    }

                    //这里你可以输出一下看看
                    //context.Response.Write(url.Page + "<br>" + newUrl+"<br>");
                    //开始把用户便于记忆的URL替换成程序能读懂的url
                    context.RewritePath(newPage, string.Empty, newQueryString);
                }
            }
        }
    }
    public class SiteUrls
    {
        //定义成volatitle类型主要是为了多线程访问方便,在这个示例程序中没什么实际意义，项目大了就有用了
        private static volatile SiteUrls instance = null;
        string UrlsFile = HttpContext.Current.Server.MapPath("~/urls.config");
        //定义两个属性
        private System.Collections.ArrayList _Urls;
        public System.Collections.ArrayList Urls
        {
            get { return _Urls; }
            set { _Urls = value; }
        }
        //这个就是个键植对 表害怕一点也不高深
        //private System.Collections.Specialized.NameValueCollection _Paths;
        //public System.Collections.Specialized.NameValueCollection Paths
        //{
        //    get { return _Paths; }
        //    set { _Paths = value; }
        //}
        //构造函数
        private SiteUrls()
        {
            Urls = new System.Collections.ArrayList();
            //Paths = new System.Collections.Specialized.NameValueCollection();
            //以XML个数读取那CONFIG文件
            XmlDocument urlconfig = new XmlDocument();
            urlconfig.Load(UrlsFile);
            XmlNode root = urlconfig.SelectSingleNode("urls");
            foreach (XmlNode n in root.ChildNodes)
            {
                //XmlNodeType.Comment如果不是注释
                if (n.NodeType != XmlNodeType.Comment && n.Name.ToLower() == "rewrite")
                {
                    XmlAttribute name = n.Attributes["name"];
                    //XmlAttribute path = n.Attributes["path"];
                    XmlAttribute page = n.Attributes["page"];
                    XmlAttribute querystring = n.Attributes["querystring"];
                    XmlAttribute pattern = n.Attributes["pattern"];

                    //if (name != null && path != null && page != null && querystring != null && pattern != null)
                    if (name != null && page != null && querystring != null && pattern != null)
                    {
                        //Paths.Add(name.Value, path.Value);
                        //压进去的都是url实体类
                        Urls.Add(new URLRewrite(name.Value, pattern.Value, page.Value.Replace("^", "&"), querystring.Value.Replace("^", "&")));
                    }
                }
            }
        }
        //用方法实例化
        public static SiteUrls GetSiteUrls()
        {
            if (instance == null)
            {
                instance = new SiteUrls();
            }
            return instance;
        }

        #region url实体类
        public class URLRewrite
        {
            #region 成员变量
            private string _Name;
            public string Name
            {
                get { return _Name; }
                set { _Name = value; }
            }

            private string _Pattern;
            public string Pattern
            {
                get { return _Pattern; }
                set { _Pattern = value; }
            }

            private string _Page;
            public string Page
            {
                get { return _Page; }
                set { _Page = value; }
            }

            private string _QueryString;
            public string QueryString
            {
                get { return _QueryString; }
                set { _QueryString = value; }
            }
            #endregion
            #region 构造函数
            public URLRewrite(string name, string pattern, string page, string querystring)
            {
                _Name = name;
                _Pattern = pattern;
                _Page = page;
                _QueryString = querystring;
            }
            #endregion
        }
        #endregion
    }



    /// <summary>
    /// 处理.html文件
    /// </summary>
    public sealed class HtmlHandler : IHttpHandler
    {

        public bool IsReusable { get { return false; } }
        public void ProcessRequest(HttpContext context)
        {
            // 接受到了一个来自html文件的请求
            string requestPath = context.Request.Path.ToLower();
            //SiteUrls是下面的一个类，这里大家可以重构下
            foreach (SiteUrls.URLRewrite url in SiteUrls.GetSiteUrls().Urls)
            {
                //是否找到了匹配选项
                if (Regex.IsMatch(requestPath, url.Pattern, RegexOptions.None | RegexOptions.IgnoreCase))
                {
                    //开始替换成我们程序能读懂的url
                    //用querystring按照patten方式替换pathinfo?querystring
                    string newUrl = Regex.Replace(requestPath.Substring(context.Request.Path.LastIndexOf("/")), url.Pattern, url.QueryString, RegexOptions.None | RegexOptions.IgnoreCase);
                    //这里你可以输出一下看看
                    //context.Response.Write(url.Page + "<br>" + newUrl+"<br>");
                    //开始把用户便于记忆的URL替换成程序能读懂的url
                    context.RewritePath(url.Page, string.Empty, newUrl);
                }
            }
        }


    }
}